﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;
using Macds.Core.Serialization;
using Macds.Core.Web;
using Microsoft.CSharp;

namespace Macds.Core.XML
{
    public class XMLHelper : WebRequestBase
    {
        public XMLSchemaClassBuilderManager XmlManager;

        public string GetJSON(string xmlURL)
        {
            object xmlObject = GetObject(xmlURL);

            return new JavaScriptSerializer().Serialize(xmlObject);
        }

        public object GetObject(string xmlInfo)
        {
            return GetObject(xmlInfo, false);
        }

        public object GetObject(string xmlInfo, bool xmlString)
        {
            if (XmlManager == null)
                XmlManager = new XMLSchemaClassBuilderManager(xmlInfo);

            XmlManager.IsXMLString = xmlString;

            object xmlObject = CreateObject(xmlInfo);
            string xmlData = XmlManager.RemoveAllNamespaces();

            Type xmlObjectType = xmlObject.GetType();
            Converter converter = new Converter();

            var objValues = typeof(Converter)
                        .GetMethod("GetObjectFromXml")
                        .MakeGenericMethod(xmlObjectType)
                            .Invoke(converter, new object[] { xmlData });

            return objValues;
        }

        private object CreateObject(string xmlURL)
        {
            if (XmlManager == null)
                XmlManager = new XMLSchemaClassBuilderManager(xmlURL);

            var data = "using System.Collections.Generic;\r\n";
            data += "using System;\r\n\r\n";
            data += XmlManager.GetClassesAtOnce();

            var compilerParameters = new CompilerParameters();
            compilerParameters.GenerateExecutable = false;
            compilerParameters.GenerateInMemory = true;
            compilerParameters.IncludeDebugInformation = true;
            compilerParameters.ReferencedAssemblies.Add("System.XML.dll");
            compilerParameters.ReferencedAssemblies.Add("System.Xml.Serialization.dll");

            var cCompiler = CSharpCodeProvider.CreateProvider("CSharp");
            var compileResult = cCompiler.CompileAssemblyFromSource(compilerParameters, data.ToString());

            if (compileResult.Errors.HasErrors)
            {
                StringBuilder errorMsg = new StringBuilder();
                foreach (CompilerError error in compileResult.Errors)
                {
                    errorMsg.Append(error.ErrorText + "\r\n");
                }

                throw new Exception(errorMsg.ToString());
            }

            return compileResult.CompiledAssembly.CreateInstance(XmlManager.RootClassType);
        }
    }
}
